using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Runtime.InteropServices;
using AOT;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

namespace JSDBV1
{
#if UNITY_WEBGL

    public class IndexedDB : MonoBehaviour
    {
        [DllImport("__Internal")]
        public static extern void initJsStringToBuffer();

        [DllImport("__Internal")]
        public static extern void dbAddData(string key, string content,
            [MarshalAs(UnmanagedType.FunctionPtr)] strCallback result = null);

        [DllImport("__Internal")]
        public static extern void dbAddDataInt(string key, int content,
            [MarshalAs(UnmanagedType.FunctionPtr)] strCallback result = null);

        [DllImport("__Internal")]
        public static extern void dbAddDataFloat(string key, float content,
            [MarshalAs(UnmanagedType.FunctionPtr)] strCallback result = null);

        [DllImport("__Internal")]
        public static extern void dbGetData(string key,
            [MarshalAs(UnmanagedType.FunctionPtr)] strCallback result = null);

        [DllImport("__Internal")]
        public static extern void dbGetDataInt(string key,
            [MarshalAs(UnmanagedType.FunctionPtr)] intCallback result = null);

        [DllImport("__Internal")]
        public static extern void dbGetDataFloat(string key,
            [MarshalAs(UnmanagedType.FunctionPtr)] floatCallback result = null);

        [DllImport("__Internal")]
        public static extern void dbDelData(string key);


        [MonoPInvokeCallback(typeof(strCallback))]
        public static void ResultStr(string value)
        {
            Debug.Log($"[unity.ResultStr] js back result===>{value},{Time.frameCount},{Time.realtimeSinceStartup}");
        }

        [MonoPInvokeCallback(typeof(intCallback))]
        public static void ResultInt(int value)
        {
            Debug.Log($"[unity.ResultInt] js back result===>{value},{Time.frameCount},{Time.realtimeSinceStartup}");
        }

        [MonoPInvokeCallback(typeof(floatCallback))]
        public static void Resultfloat(float value)
        {
            Debug.Log($"[unity.Resultfloat] js back result===>{value},{Time.frameCount},{Time.realtimeSinceStartup}");
        }


        public InputField key;
        public InputField content;
        public Dropdown dropdown;

        public enum DataOption
        {
            set,
            get,
            del
        }

        private void Awake()
        {
#if UNITY_WEBGL && !UNITY_EDITOR
        initJsStringToBuffer();
#endif
        }


        void DBOption(DataOption option, string content = "")
        {
            switch (option)
            {
                case DataOption.set:
                    switch (dropdown.value)
                    {
                        case 0:
                            dbAddData(key.text, content, ResultStr);
                            break;
                        case 1:
                            dbAddDataInt(key.text, int.Parse(content), ResultStr);
                            break;
                        case 2:
                            dbAddDataFloat(key.text, float.Parse(content), ResultStr);
                            break;
                    }

                    break;
                case DataOption.get:
                    switch (dropdown.value)
                    {
                        case 0:
                            dbGetData(key.text, ResultStr);
                            break;
                        case 1:
                            dbGetDataInt(key.text, ResultInt);
                            break;
                        case 2:
                            dbGetDataFloat(key.text, Resultfloat);
                            break;
                    }

                    break;
            }
        }


        private void OnGUI()
        {
            if (GUILayout.Button("add&put no callback") && key.text.Length > 0 && content.text.Length > 0)
            {
                Debug.Log($"click add:{Time.frameCount},{Time.realtimeSinceStartup}");
                dbAddData(key.text, content.text);
            }

            if (GUILayout.Button("add&put") && key.text.Length > 0 && content.text.Length > 0)
            {
                Debug.Log($"click add:{Time.frameCount},{Time.realtimeSinceStartup}");
                DBOption(DataOption.set, content.text);
            }

            if (GUILayout.Button("Read") && key.text.Length > 0)
            {
                Debug.Log($"click read:{Time.frameCount},{Time.realtimeSinceStartup}");
                DBOption(DataOption.get);
            }

            if (GUILayout.Button("del") && key.text.Length > 0)
            {
                dbDelData(key.text);
            }


            if (GUILayout.Button("add&put & Read") && key.text.Length > 0)
            {
                Debug.Log($"click Add & Read:{Time.frameCount},{Time.realtimeSinceStartup}");
                dbAddData(key.text, content.text, ResultStr);
                dbGetData(key.text, ResultStr);
            }

            if (GUILayout.Button("big file Add & Read") && key.text.Length > 0)
            {
                StartCoroutine(_SaveFile());
            }
        }

        private IEnumerator _SaveFile()
        {
            var web = UnityWebRequest.Get($"StreamingAssets/file.txt?ran={Time.realtimeSinceStartup}");
            yield return web.SendWebRequest();
            if (string.IsNullOrEmpty(web.error))
            {
                Debug.Log(web.downloadHandler.text);
                Debug.Log($"click big file add&put & Read:{Time.frameCount},{Time.realtimeSinceStartup}");
                dbAddData(key.text, web.downloadHandler.text, ResultStr);
                dbGetData(key.text, ResultStr);
            }
            else
            {
                Debug.LogError($"big file Add & Read:{web.error}");
            }
        }
    }

#endif
}